package util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import response.BaseResponse;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

public class HttpUtil {


    private static final CloseableHttpClient CLIENT = HttpClients.createDefault();

    /**
     * 发起POST请求
     * @param url
     * @param param
     * @param <T>
     * @param <E>
     * @return
     */
    public static <T,E> T get(String url, E param,TypeReference<BaseResponse<T>> tr){
        try{
            String request = setGetParam(param);
            String realUrl;
            if(null == request){
                realUrl = url;
            }else{
                realUrl = url + "?" + request;
            }
            System.out.println("请求地址为：" + realUrl);
            HttpGet get = new HttpGet(realUrl);
            get.addHeader("Authorization",TrainConstant.AUTHORIZATION);
            T result = CLIENT.execute(get,res->{
                if(res.getCode() == HttpStatus.SC_OK && null != res.getEntity()){
                    String response = EntityUtils.toString(res.getEntity());
                    BaseResponse<T> ret = JSON.parseObject(response,tr);
                    System.out.println("请求结果为：" + response);
                    if(ret.getCode() != null && ret.getCode().equals("200")){
                        return ret.getData();
                    }else{
                        return  null;
                    }
                }else{
                    return null;
                }
            });
            return result;
        }catch (Exception e){
            System.out.println("发起Http GET 请求异常：" + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    public static <T,E> T post(String url, E param, TypeReference<BaseResponse<T>> tr){
        String paramStr = JSON.toJSONString(param);
        try{
            System.out.println("请求参数：" + paramStr);
            HttpPost post = new HttpPost(url);
            post.addHeader("Content-Type","application/json");
            post.addHeader("Authorization",TrainConstant.AUTHORIZATION);
            post.setEntity(new StringEntity(paramStr));
            T result = CLIENT.execute(post,res->{
                if(res.getCode() == HttpStatus.SC_OK && null != res.getEntity()){
                    String response = EntityUtils.toString(res.getEntity());
                    BaseResponse<T> ret = JSON.parseObject(response,tr);
                    System.out.println("请求结果为：" + response);
                    if(ret.getCode() != null && ret.getCode().equals("200")){
                        return ret.getData();
                    }else{
                        return  null;
                    }
                }else {
                    return null;
                }
            });
            return result;
        }catch (Exception e){
            System.out.println("请求错误：" + e.getMessage());
        }
        return null;
    }

    private static <T> String setGetParam(T param) throws NoSuchMethodException, IOException, ParseException, InvocationTargetException, IllegalAccessException {
        if(param == null){
            System.out.println("请求参数为空");
            return null;
        }
        Field[] fields = param.getClass().getDeclaredFields();
        if(null == fields || fields.length  == 0){
            System.out.println("请求参数为空");
            return null;
        }
        List<NameValuePair> paramList = new ArrayList<>();
        for(Field field : fields){
            field.setAccessible(Boolean.TRUE);
            String name = field.getName();
            Method method = param.getClass().getDeclaredMethod("get" + StringUtils.capitalize(name));
            String value = method.invoke(param).toString();
            paramList.add(new BasicNameValuePair(field.getName(),value));
        }
        String result = EntityUtils.toString(new UrlEncodedFormEntity(paramList, Charset.defaultCharset()));
        System.out.println("接口请求参数为：" + result);
        return result;
    }
}
